home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2001 May / may_2001.iso / intercd / root / Multimedia / ^DivX_Article / virtualdub / VirtualDub-source-1_4d / f_boxblur.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-20  |  22.6 KB  |  922 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    Copyright (C) 1998-2001 Avery Lee
  3. //
  4. //    This program is free software; you can redistribute it and/or modify
  5. //    it under the terms of the GNU General Public License as published by
  6. //    the Free Software Foundation; either version 2 of the License, or
  7. //    (at your option) any later version.
  8. //
  9. //    This program is distributed in the hope that it will be useful,
  10. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. //    GNU General Public License for more details.
  13. //
  14. //    You should have received a copy of the GNU General Public License
  15. //    along with this program; if not, write to the Free Software
  16. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. #include "VirtualDub.h"
  19.  
  20. #include <windows.h>
  21. #include <stdio.h>
  22. #include <commctrl.h>
  23.  
  24. #include "ScriptInterpreter.h"
  25. #include "ScriptError.h"
  26. #include "ScriptValue.h"
  27.  
  28. #include "resource.h"
  29. #include "filter.h"
  30. #include "cpuaccel.h"
  31.  
  32. extern HINSTANCE g_hInst;
  33. extern "C" unsigned char YUV_clip_table[];
  34.  
  35. //#define DO_UNSHARP_FILTER
  36.  
  37. ///////////////////////////////////////////////////////////////////////////
  38.  
  39. int boxInitProc(FilterActivation *fa, const FilterFunctions *ff);
  40. int boxRunProc(const FilterActivation *fa, const FilterFunctions *ff);
  41. int boxStartProc(FilterActivation *fa, const FilterFunctions *ff);
  42. int boxEndProc(FilterActivation *fa, const FilterFunctions *ff);
  43. long boxParamProc(FilterActivation *fa, const FilterFunctions *ff);
  44. int boxConfigProc(FilterActivation *fa, const FilterFunctions *ff, HWND hwnd);
  45. void boxStringProc(const FilterActivation *fa, const FilterFunctions *ff, char *str);
  46. void boxScriptConfig(IScriptInterpreter *isi, void *lpVoid, CScriptValue *argv, int argc);
  47. bool boxFssProc(FilterActivation *fa, const FilterFunctions *ff, char *buf, int buflen);
  48.  
  49. ///////////////////////////////////////////////////////////////////////////
  50.  
  51. typedef unsigned short Pixel16;
  52.  
  53. typedef struct BoxFilterData {
  54.     IFilterPreview *ifp;
  55.     Pixel32 *rows;
  56.     Pixel16 *trow;
  57.     int     filter_width;
  58.     int     filter_power;
  59. } BoxFilterData;
  60.  
  61. ScriptFunctionDef box_func_defs[]={
  62.     { (ScriptFunctionPtr)boxScriptConfig, "Config", "0ii" },
  63.     { NULL },
  64. };
  65.  
  66. CScriptObject box_obj={
  67.     NULL, box_func_defs
  68. };
  69.  
  70. struct FilterDefinition filterDef_box = {
  71.  
  72.     NULL, NULL, NULL,        // next, prev, module
  73.     "box blur",                    // name
  74.     "Performs a fast box, triangle, or cubic blur.",
  75.                             // desc
  76.     NULL,                    // maker
  77.     NULL,                    // private_data
  78.     sizeof(BoxFilterData),    // inst_data_size
  79.  
  80.     boxInitProc,            // initProc
  81.     NULL,                    // deinitProc
  82.     boxRunProc,             // runProc
  83.     boxParamProc,            // paramProc
  84.     boxConfigProc,            // configProc
  85.     boxStringProc,            // stringProc
  86.     boxStartProc,            // startProc
  87.     boxEndProc,             // endProc
  88.  
  89.     &box_obj,                // script_obj
  90.     boxFssProc,             // fssProc
  91.  
  92. };
  93.  
  94. ///////////////////////////////////////////////////////////////////////////
  95.  
  96. extern "C" int __declspec(dllexport) __cdecl VirtualdubFilterModuleInit2(FilterModule *fm, const FilterFunctions *ff, int& vdfd_ver, int& vdfd_compat);
  97. extern "C" void __declspec(dllexport) __cdecl VirtualdubFilterModuleDeinit(FilterModule *fm, const FilterFunctions *ff);
  98.  
  99. static FilterDefinition *fd_box;
  100.  
  101. ///////////////////////////////////////////////////////////////////////////
  102.  
  103. int __declspec(dllexport) __cdecl VirtualdubFilterModuleInit2(FilterModule *fm, const FilterFunctions *ff, int& vdfd_ver, int& vdfd_compat) {
  104.     if (!(fd_box = ff->addFilter(fm, &filterDef_box, sizeof(FilterDefinition))))
  105.         return 1;
  106.  
  107.     vdfd_ver = VIRTUALDUB_FILTERDEF_VERSION;
  108.     vdfd_compat = VIRTUALDUB_FILTERDEF_COMPATIBLE;
  109.  
  110.     return 0;
  111. }
  112.  
  113. void __declspec(dllexport) __cdecl VirtualdubFilterModuleDeinit(FilterModule *fm, const FilterFunctions *ff) {
  114.     ff->removeFilter(fd_box);
  115. }
  116.  
  117. ///////////////////////////////////////////////////////////////////////////
  118.  
  119. int boxInitProc(FilterActivation *fa, const FilterFunctions *ff) {
  120.     BoxFilterData *mfd = (BoxFilterData *)fa->filter_data;
  121.  
  122.     mfd->filter_width = 1;
  123.     mfd->filter_power = 1;
  124.  
  125.     return 0;
  126. }
  127.  
  128. int boxStartProc(FilterActivation *fa, const FilterFunctions *ff) {
  129.     BoxFilterData *mfd = (BoxFilterData *)fa->filter_data;
  130.  
  131.     if (mfd->filter_power < 1)
  132.         mfd->filter_power = 1;
  133.  
  134.     if (mfd->filter_width < 1)
  135.         mfd->filter_width = 1;
  136.  
  137.     mfd->trow = NULL;
  138.  
  139.     if (!(mfd->rows = (Pixel32 *)allocmem(((fa->dst.w+1)&-2)*4*fa->dst.h)))
  140.         return 1;
  141.  
  142.     if (!(mfd->trow = (Pixel16 *)allocmem(fa->dst.w*8)))
  143.         return 1;
  144.  
  145.     return 0;
  146. }
  147.  
  148. static void box_filter_row(Pixel32 *dst, Pixel32 *src, int filtwidth, int cnt, int mult) {
  149.     int i;
  150.     unsigned r, g, b;
  151.     Pixel32 A, B;
  152.  
  153.     A = src[0];
  154.     r = (int)(unsigned char)(A>>16) * filtwidth;
  155.     g = (int)(unsigned char)(A>> 8) * filtwidth;
  156.     b = (int)(unsigned char)(A      ) * filtwidth;
  157.  
  158.     i = filtwidth + 1;
  159.     do {
  160.         B = *src++;
  161.  
  162.         r += (int)(unsigned char)(B>>16);
  163.         g += (int)(unsigned char)(B>> 8);
  164.         b += (int)(unsigned char)(B    );
  165.     } while(--i);
  166.  
  167.     i = filtwidth;
  168.  
  169.     do {
  170.         *dst++ = ((r*mult)&0xff0000) + (((g*mult)>>8)&0xff00) + ((b*mult)>>16);
  171.  
  172.         B = src[0];
  173.         ++src;
  174.  
  175.         r = r - (int)(unsigned char)(A>>16) + (int)(unsigned char)(B>>16);
  176.         g = g - (int)(unsigned char)(A>> 8) + (int)(unsigned char)(B>> 8);
  177.         b = b - (int)(unsigned char)(A      ) + (int)(unsigned char)(B    );
  178.  
  179.     } while(--i);
  180.  
  181.     i = cnt - 2*filtwidth - 1;
  182.     do {
  183.         *dst++ = ((r*mult)&0xff0000) + (((g*mult)>>8)&0xff00) + ((b*mult)>>16);
  184.  
  185.         A = src[-(2*filtwidth+1)];
  186.         B = src[0];
  187.         ++src;
  188.  
  189.         r = r - (int)(unsigned char)(A>>16) + (int)(unsigned char)(B>>16);
  190.         g = g - (int)(unsigned char)(A>> 8) + (int)(unsigned char)(B>> 8);
  191.         b = b - (int)(unsigned char)(A      ) + (int)(unsigned char)(B    );
  192.     } while(--i);
  193.  
  194.     i = filtwidth;
  195.     do {
  196.         *dst++ = ((r*mult)&0xff0000) + (((g*mult)>>8)&0xff00) + ((b*mult)>>16);
  197.  
  198.         A = src[-(2*filtwidth+1)];
  199.         ++src;
  200.  
  201.         r = r - (int)(unsigned char)(A>>16) + (int)(unsigned char)(B>>16);
  202.         g = g - (int)(unsigned char)(A>> 8) + (int)(unsigned char)(B>> 8);
  203.         b = b - (int)(unsigned char)(A      ) + (int)(unsigned char)(B    );
  204.  
  205.     } while(--i);
  206.  
  207.     *dst = ((r*mult)&0xff0000) + (((g*mult)>>8)&0xff00) + ((b*mult)>>16);
  208. }
  209.  
  210. static void __declspec(naked) box_filter_row_MMX(Pixel32 *dst, Pixel32 *src, int filtwidth, int cnt, int divisor) {
  211.     __asm {
  212.         push        ebx
  213.  
  214.         mov            ecx,[esp+12+4]            ;ecx = filtwidth
  215.         mov            eax,[esp+8+4]            ;eax = src
  216.         movd        mm6,ecx
  217.         pxor        mm7,mm7
  218.         movd        mm5,[eax]                ;A = source pixel
  219.         punpcklwd    mm6,mm6
  220.         pcmpeqw        mm4,mm4                    ;mm4 = all -1's
  221.         punpckldq    mm6,mm6
  222.         psubw        mm6,mm4                    ;mm6 = filtwidth+1
  223.         punpcklbw    mm5,mm7                    ;mm5 = src[0] (word)
  224.         movq        mm0,mm5                    ;mm0 = A
  225.         pmullw        mm5,mm6                    ;mm5 = src[0]*(filtwidth+1)
  226.         add            eax,4                    ;next source pixel
  227. xloop1:
  228.         movd        mm1,[eax]                ;B = next source pixel
  229.         pxor        mm7,mm7
  230.         punpcklbw    mm1,mm7
  231.         add            eax,4
  232.         paddw        mm5,mm1
  233.         dec            ecx
  234.         jne            xloop1
  235.  
  236.         mov            ecx,[esp+12+4]            ;ecx = filtwidth
  237.         movd        mm6,[esp+20+4]
  238.         punpcklwd    mm6,mm6
  239.         mov            edx,[esp+4+4]            ;edx = dst
  240.         punpckldq    mm6,mm6
  241. xloop2:
  242.         movd        mm1,[eax]                ;B = next source pixel
  243.         movq        mm2,mm5                    ;mm1 = accum
  244.  
  245.         pmulhw        mm2,mm6
  246.         punpcklbw    mm1,mm7
  247.  
  248.         psubw        mm5,mm0                    ;accum -= A
  249.         add            eax,4
  250.  
  251.         paddw        mm5,mm1                    ;accum += B
  252.         add            edx,4
  253.  
  254.         packuswb    mm2,mm2
  255.         dec            ecx
  256.  
  257.         movd        [edx-4],mm2
  258.         jne            xloop2
  259.  
  260.         ;main loop.
  261.         
  262.         mov            ebx,[esp+12+4]            ;ebx = filtwidth
  263.         mov            ecx,[esp+16+4]            ;ecx = cnt
  264.         lea            ebx,[ebx+ebx+1]            ;ebx = 2*filtwidth+1
  265.         sub            ecx,ebx                    ;ecx = cnt - (2*filtwidth+1)
  266.         shl            ebx,2
  267.         neg            ebx                        ;ebx = -4*(2*filtwidth+1)
  268. xloop3:
  269.         movd        mm0,[eax+ebx]            ;mm0 = A = src[-(2*filtwidth+1)]
  270.         movq        mm2,mm5
  271.  
  272.         movd        mm1,[eax]                ;mm0 = B = src[0]
  273.         pmulhw        mm2,mm6
  274.  
  275.         punpcklbw    mm0,mm7
  276.         add            edx,4
  277.  
  278.         punpcklbw    mm1,mm7
  279.         add            eax,4
  280.  
  281.         psubw        mm5,mm0                    ;accum -= A
  282.         packuswb    mm2,mm2                    ;pack finished pixel
  283.  
  284.         paddw        mm5,mm1                    ;accum += B
  285.         dec            ecx
  286.  
  287.         movd        [edx-4],mm2
  288.         jne            xloop3
  289.  
  290.         ;finish up remaining pixels
  291.  
  292.         mov            ecx,[esp+12+4]            ;ecx = filtwidth
  293. xloop4:
  294.         movd        mm0,[eax+ebx]            ;mm0 = A = src[-(2*filtwidth+1)]
  295.         movq        mm2,mm5
  296.  
  297.         pmulhw        mm2,mm6
  298.         add            edx,4
  299.  
  300.         punpcklbw    mm0,mm7
  301.         add            eax,4
  302.  
  303.         psubw        mm5,mm0                    ;accum -= A
  304.         packuswb    mm2,mm2                    ;pack finished pixel
  305.  
  306.         paddw        mm5,mm1                    ;accum += B
  307.         dec            ecx
  308.  
  309.         movd        [edx-4],mm2
  310.         jne            xloop4
  311.  
  312.         pmulhw        mm5,mm6
  313.         packuswb    mm5,mm5
  314.         movd        [edx],mm5
  315.  
  316.         pop            ebx
  317.         ret
  318.     }
  319. }
  320.  
  321. ///////////////////////////////////////////////////////////////////////////
  322.  
  323. static void box_filter_mult_row(Pixel16 *dst, Pixel32 *src, int cnt, int mult) {
  324.     Pixel32 A;
  325.  
  326.     if (MMX_enabled)
  327.         __asm {
  328.             mov            eax,src
  329.             movd        mm6,mult
  330.             mov            edx,dst
  331.             punpcklwd    mm6,mm6
  332.             mov            ecx,cnt
  333.             punpckldq    mm6,mm6
  334. xloop:
  335.             movd        mm0,[eax+ecx*4-4]
  336.             pxor        mm7,mm7
  337.  
  338.             punpcklbw    mm0,mm7
  339.  
  340.             pmullw        mm0,mm6
  341.  
  342.             movq        [edx+ecx*8-8],mm0
  343.  
  344.             dec            ecx
  345.             jne            xloop
  346.         }
  347.     else
  348.         do {
  349.             A = *src++;
  350.  
  351.             dst[0] = (int)(unsigned char)(A>>16) * mult;
  352.             dst[1] = (int)(unsigned char)(A>> 8) * mult;
  353.             dst[2] = (int)(unsigned char)(A    ) * mult;
  354.  
  355.             dst += 3;
  356.         } while(--cnt);
  357. }
  358.  
  359. static void box_filter_add_row(Pixel16 *dst, Pixel32 *src, int cnt) {
  360.     Pixel32 A;
  361.  
  362.     if (MMX_enabled)
  363.         __asm {
  364.             mov            eax,src
  365.             mov            edx,dst
  366.             mov            ecx,cnt
  367. xloop:
  368.             movd        mm0,[eax+ecx*4-4]
  369.             pxor        mm7,mm7
  370.  
  371.             punpcklbw    mm0,mm7
  372.  
  373.             paddw        mm0,[edx+ecx*8-8]
  374.  
  375.             movq        [edx+ecx*8-8],mm0
  376.  
  377.             dec            ecx
  378.             jne            xloop
  379.         }
  380.     else
  381.         do {
  382.             A = *src++;
  383.  
  384.             dst[0] += (int)(unsigned char)(A>>16);
  385.             dst[1] += (int)(unsigned char)(A>> 8);
  386.             dst[2] += (int)(unsigned char)(A    );
  387.  
  388.             dst += 3;
  389.         } while(--cnt);
  390. }
  391.  
  392. static void box_filter_produce_row(Pixel32 *dst, Pixel16 *tmp, Pixel32 *src_add, Pixel32 *src_sub, int cnt, int filter_width) {
  393.     Pixel32 A, B;
  394.     Pixel16 r, g, b;
  395.     int mult = 0x10000 / (2*filter_width+1);
  396.  
  397.     if (MMX_enabled)
  398.         __asm {
  399.             mov            eax,src_add
  400.             movd        mm6,mult
  401.             mov            edx,tmp
  402.             punpcklwd    mm6,mm6
  403.             mov            ecx,cnt
  404.             punpckldq    mm6,mm6
  405.             mov            ebx,src_sub
  406.             mov            edi,dst
  407. xloop:
  408.             movq        mm2,[edx+ecx*8-8]
  409.             pxor        mm7,mm7
  410.  
  411.             movd        mm0,[eax+ecx*4-4]
  412.             movq        mm3,mm2
  413.  
  414.             movd        mm1,[ebx+ecx*4-4]
  415.             pmulhw        mm2,mm6
  416.  
  417.             punpcklbw    mm0,mm7
  418.             ;
  419.  
  420.             punpcklbw    mm1,mm7
  421.             paddw        mm0,mm3
  422.  
  423.             psubw        mm0,mm1
  424.             packuswb    mm2,mm2
  425.  
  426.             movq        [edx+ecx*8-8],mm0
  427.  
  428.             movd        [edi+ecx*4-4],mm2
  429.  
  430.             dec            ecx
  431.             jne            xloop
  432.         }
  433.     else
  434.         do {
  435.             A = *src_add++;
  436.             B = *src_sub++;
  437.  
  438.             r = tmp[0];
  439.             g = tmp[1];
  440.             b = tmp[2];
  441.  
  442.             *dst++    = ((r*mult) & 0xff0000)
  443.                     +(((g*mult) & 0xff0000) >> 8)
  444.                     + ((b*mult) >> 16);
  445.  
  446.             tmp[0] = r + (int)(unsigned char)(A>>16) - (int)(unsigned char)(B>>16);
  447.             tmp[1] = g + (int)(unsigned char)(A>> 8) - (int)(unsigned char)(B>> 8);
  448.             tmp[2] = b + (int)(unsigned char)(A    ) - (int)(unsigned char)(B     );
  449.  
  450.             tmp += 3;
  451.         } while(--cnt);
  452. }
  453.  
  454. static void box_filter_produce_row2(Pixel32 *dst, Pixel16 *tmp, int cnt, int filter_width) {
  455.     Pixel16 r, g, b;
  456.     int mult = 0x10000 / (2*filter_width+1);
  457.  
  458.     if (MMX_enabled)
  459.         __asm {
  460.             movd        mm6,mult
  461.             mov            eax,tmp
  462.             punpcklwd    mm6,mm6
  463.             mov            ecx,cnt
  464.             punpckldq    mm6,mm6
  465.             mov            edx,dst
  466. xloop:
  467.             movq        mm2,[eax+ecx*8-8]
  468.             pxor        mm7,mm7
  469.  
  470.             pmulhw        mm2,mm6
  471.  
  472.             packuswb    mm2,mm2
  473.  
  474.             movd        [edx+ecx*4-4],mm2
  475.  
  476.             dec            ecx
  477.             jne            xloop
  478.         }
  479.     else
  480.         do {
  481.             r = tmp[0];
  482.             g = tmp[1];
  483.             b = tmp[2];
  484.  
  485.             *dst++    = ((r*mult) & 0xff0000)
  486.                     +(((g*mult) & 0xff0000) >> 8)
  487.                     + ((b*mult) >> 16);
  488.  
  489.             tmp += 3;
  490.         } while(--cnt);
  491. }
  492.  
  493. ///////////////////////////////////////////////////////////////////////
  494.  
  495. #ifdef DO_UNSHARP_FILTER
  496.  
  497. static const __int64 x0080w = 0x0080008000800080i64;
  498.  
  499. static void box_unsharp_produce_row(Pixel32 *dst, Pixel16 *tmp, Pixel32 *src_add, Pixel32 *src_sub, int cnt, int filter_width, Pixel32 *orig) {
  500.     Pixel32 A, B;
  501.     Pixel16 r, g, b;
  502.     int mult = 0x10000 / (2*filter_width+1);
  503.  
  504.     if (MMX_enabled)
  505.         __asm {
  506.             mov            eax,src_add
  507.             movd        mm6,mult
  508.             mov            edx,tmp
  509.             punpcklwd    mm6,mm6
  510.             mov            ecx,cnt
  511.             punpckldq    mm6,mm6
  512.             mov            ebx,src_sub
  513.             mov            edi,dst
  514.             mov            esi,orig
  515.             movq        mm4,x0080w
  516. xloop:
  517.             movq        mm2,[edx+ecx*8-8]
  518.             pxor        mm7,mm7
  519.  
  520.             movd        mm0,[eax+ecx*4-4]
  521.             movq        mm3,mm2
  522.  
  523.             movd        mm1,[ebx+ecx*4-4]
  524.             pmulhw        mm2,mm6
  525.  
  526.             movd        mm5,[esi+ecx*4-4]
  527.             punpcklbw    mm0,mm7
  528.  
  529.             punpcklbw    mm5,mm7
  530.             paddw        mm0,mm3
  531.  
  532.             punpcklbw    mm1,mm7
  533.             paddw        mm5,mm4
  534.  
  535.             psubw        mm0,mm1
  536.             psubw        mm5,mm2
  537.  
  538.             packuswb    mm5,mm5
  539.  
  540.             movq        [edx+ecx*8-8],mm0
  541.  
  542.             movd        [edi+ecx*4-4],mm5
  543.  
  544.             dec            ecx
  545.             jne            xloop
  546.         }
  547.     else {
  548.         unsigned char *dst2 = (unsigned char *)dst;
  549.  
  550.         do {
  551.             A = *src_add++;
  552.             B = *src_sub++;
  553.  
  554.             r = tmp[0];
  555.             g = tmp[1];
  556.             b = tmp[2];
  557.  
  558.             dst2[2] = YUV_clip_table[256 + 128 - ((r*mult)>>16) + ((orig[0]&0xff0000)>>16)];
  559.             dst2[1] = YUV_clip_table[256 + 128 - ((g*mult)>>16) + ((orig[0]&0x00ff00)>> 8)];
  560.             dst2[0] = YUV_clip_table[256 + 128 - ((b*mult)>>16) + ((orig[0]&0x0000ff)    )];
  561.  
  562.             tmp[0] = r + (int)(unsigned char)(A>>16) - (int)(unsigned char)(B>>16);
  563.             tmp[1] = g + (int)(unsigned char)(A>> 8) - (int)(unsigned char)(B>> 8);
  564.             tmp[2] = b + (int)(unsigned char)(A    ) - (int)(unsigned char)(B     );
  565.  
  566.             tmp += 3;
  567.             ++orig;
  568.             dst2 += 4;
  569.         } while(--cnt);
  570.     }
  571. }
  572.  
  573. static void box_unsharp_produce_row2(Pixel32 *dst, Pixel16 *tmp, int cnt, int filter_width, Pixel32 *orig) {
  574.     Pixel16 r, g, b;
  575.     int mult = 0x10000 / (2*filter_width+1);
  576.  
  577.     if (MMX_enabled)
  578.         __asm {
  579.             movd        mm6,mult
  580.             mov            eax,tmp
  581.             punpcklwd    mm6,mm6
  582.             mov            ecx,cnt
  583.             punpckldq    mm6,mm6
  584.             mov            edx,dst
  585.             mov            ebx,orig
  586.             movq        mm4,x0080w
  587. xloop:
  588.             movq        mm2,[eax+ecx*8-8]
  589.             pxor        mm7,mm7
  590.  
  591.             movd        mm3,[ebx+ecx*4-4]
  592.             pmulhw        mm2,mm6
  593.  
  594.             punpcklbw    mm3,mm7
  595.  
  596.             paddw        mm3,mm4
  597.  
  598.             psubw        mm3,mm2
  599.  
  600.             packuswb    mm3,mm3
  601.  
  602.             movd        [edx+ecx*4-4],mm3
  603.  
  604.             dec            ecx
  605.             jne            xloop
  606.         }
  607.     else {
  608.         unsigned char *dst2 = (unsigned char *)dst;
  609.  
  610.         do {
  611.             r = tmp[0];
  612.             g = tmp[1];
  613.             b = tmp[2];
  614.  
  615.             dst2[2] = YUV_clip_table[256 + 128 - ((r*mult)>>16) + ((orig[0]&0xff0000)>>16)];
  616.             dst2[1] = YUV_clip_table[256 + 128 - ((g*mult)>>16) + ((orig[0]&0x00ff00)>> 8)];
  617.             dst2[0] = YUV_clip_table[256 + 128 - ((b*mult)>>16) + ((orig[0]&0x0000ff)    )];
  618.  
  619.             tmp += 3;
  620.             dst2 += 4;
  621.             ++orig;
  622.         } while(--cnt);
  623.     }
  624. }
  625. #endif
  626.  
  627. ///////////////////////////////////////////////////////////////////////
  628.  
  629. static void box_do_vertical_pass(Pixel32 *dst, PixOffset dstpitch, Pixel32 *src, PixOffset srcpitch, Pixel16 *trow, int w, int h, int filtwidth) {
  630.     Pixel32 *srch = src;
  631.     int j;
  632.  
  633.     box_filter_mult_row(trow, src, w, filtwidth + 1);
  634.  
  635.     src = (Pixel32 *)((char *)src + srcpitch);
  636.  
  637.     for(j=0; j<filtwidth; j++) {
  638.         box_filter_add_row(trow, src, w);
  639.  
  640.         src = (Pixel32 *)((char *)src + srcpitch);
  641.     }
  642.  
  643.     for(j=0; j<filtwidth; j++) {
  644.         box_filter_produce_row(dst, trow, src, srch, w, filtwidth);
  645.  
  646.         src = (Pixel32 *)((char *)src + srcpitch);
  647.         dst = (Pixel32 *)((char *)dst + dstpitch);
  648.     }
  649.     
  650.     for(j=0; j<h - (2*filtwidth+1); j++) {
  651.         box_filter_produce_row(dst, trow, src, (Pixel32 *)((char *)src - srcpitch*(2*filtwidth+1)), w, filtwidth);
  652.  
  653.         src = (Pixel32 *)((char *)src + srcpitch);
  654.         dst = (Pixel32 *)((char *)dst + dstpitch);
  655.     }
  656.  
  657.     srch = (Pixel32 *)((char *)src - srcpitch);
  658.  
  659.     for(j=0; j<filtwidth; j++) {
  660.         box_filter_produce_row(dst, trow, srch, (Pixel32 *)((char *)src - srcpitch*(2*filtwidth+1)), w, filtwidth);
  661.  
  662.         src = (Pixel32 *)((char *)src + srcpitch);
  663.         dst = (Pixel32 *)((char *)dst + dstpitch);
  664.     }
  665.  
  666.     box_filter_produce_row2(dst, trow, w, filtwidth);
  667. }
  668.  
  669. #ifdef DO_UNSHARP_FILTER
  670. static void box_do_vertical_unsharp_pass(Pixel32 *dst, PixOffset dstpitch, Pixel32 *src, PixOffset srcpitch, Pixel32 *orig, PixOffset origpitch, Pixel16 *trow, int w, int h, int filtwidth) {
  671.     Pixel32 *srch = src;
  672.     int j;
  673.  
  674.     box_filter_mult_row(trow, src, w, filtwidth + 1);
  675.  
  676.     src = (Pixel32 *)((char *)src + srcpitch);
  677.  
  678.     for(j=0; j<filtwidth; j++) {
  679.         box_filter_add_row(trow, src, w);
  680.  
  681.         src = (Pixel32 *)((char *)src + srcpitch);
  682.     }
  683.  
  684.     for(j=0; j<filtwidth; j++) {
  685.         box_unsharp_produce_row(dst, trow, src, srch, w, filtwidth, orig);
  686.  
  687.         src = (Pixel32 *)((char *)src + srcpitch);
  688.         dst = (Pixel32 *)((char *)dst + dstpitch);
  689.         orig= (Pixel32 *)((char *)orig+ origpitch);
  690.     }
  691.     
  692.     for(j=0; j<h - (2*filtwidth+1); j++) {
  693.         box_unsharp_produce_row(dst, trow, src, (Pixel32 *)((char *)src - srcpitch*(2*filtwidth+1)), w, filtwidth, orig);
  694.  
  695.         src = (Pixel32 *)((char *)src + srcpitch);
  696.         dst = (Pixel32 *)((char *)dst + dstpitch);
  697.         orig= (Pixel32 *)((char *)orig+ origpitch);
  698.     }
  699.  
  700.     srch = (Pixel32 *)((char *)src - srcpitch);
  701.  
  702.     for(j=0; j<filtwidth; j++) {
  703.         box_unsharp_produce_row(dst, trow, srch, (Pixel32 *)((char *)src - srcpitch*(2*filtwidth+1)), w, filtwidth, orig);
  704.  
  705.         src = (Pixel32 *)((char *)src + srcpitch);
  706.         dst = (Pixel32 *)((char *)dst + dstpitch);
  707.         orig= (Pixel32 *)((char *)orig+ origpitch);
  708.     }
  709.  
  710.     box_unsharp_produce_row2(dst, trow, w, filtwidth, orig);
  711. }
  712. #endif
  713.  
  714. int boxRunProc(const FilterActivation *fa, const FilterFunctions *ff) {
  715.     BoxFilterData *mfd = (BoxFilterData *)fa->filter_data;
  716.     PixDim h;
  717.     Pixel32 *src, *dst;
  718.     Pixel32 *tsrc, *tdst, *tmp;
  719.     PixOffset srcpitch, dstpitch;
  720.     int i;
  721.  
  722.     src = fa->src.data;
  723.     dst = fa->dst.data;
  724.     tmp = mfd->rows;
  725.  
  726.     // Horizontal filtering.
  727.  
  728.     void (*pRowFilt)(Pixel32*, Pixel32*, int, int, int) = MMX_enabled ? box_filter_row_MMX : box_filter_row;
  729.     int mult = 0x10000 / (2*mfd->filter_width+1);
  730.  
  731.     h = fa->src.h;
  732.     do {
  733.         switch(mfd->filter_power) {
  734.         case 1:
  735.             pRowFilt(tmp, src, mfd->filter_width, fa->dst.w, mult);
  736.             break;
  737.         case 2:
  738.             pRowFilt(tmp, src, mfd->filter_width, fa->dst.w, mult);
  739.             pRowFilt(dst, tmp, mfd->filter_width, fa->dst.w, mult);
  740.             break;
  741.         case 3:
  742.             pRowFilt(tmp, src, mfd->filter_width, fa->dst.w, mult);
  743.             pRowFilt(dst, tmp, mfd->filter_width, fa->dst.w, mult);
  744.             pRowFilt(tmp, dst, mfd->filter_width, fa->dst.w, mult);
  745.             break;
  746.         }
  747.  
  748.         src = (Pixel32 *)((char *)src + fa->src.pitch);
  749.         dst = (Pixel32 *)((char *)dst + fa->dst.pitch);
  750.         tmp += (fa->dst.w+1)&-2;
  751.     } while(--h);
  752.  
  753.     // Vertical filtering.
  754.  
  755.     if (mfd->filter_power & 1) {
  756.         src = mfd->rows;
  757.         dst = fa->dst.data;
  758.         srcpitch = ((fa->dst.w+1)&-2)*4;
  759.         dstpitch = fa->dst.pitch;
  760.     } else {
  761.         src = fa->dst.data;
  762.         dst = mfd->rows;
  763.         srcpitch = fa->dst.pitch;
  764.         dstpitch = ((fa->dst.w+1)&-2)*4;
  765.     }
  766.  
  767. #ifndef DO_UNSHARP_FILTER
  768.     for(i=0; i<mfd->filter_power; i++) {
  769.         if (i & 1)
  770.             box_do_vertical_pass(src, srcpitch, dst, dstpitch, mfd->trow, fa->dst.w, fa->dst.h, mfd->filter_width);
  771.         else
  772.             box_do_vertical_pass(dst, dstpitch, src, srcpitch, mfd->trow, fa->dst.w, fa->dst.h, mfd->filter_width);
  773.     }
  774. #else
  775.     for(i=0; i<mfd->filter_power-1; i++) {
  776.         if (i & 1)
  777.             box_do_vertical_pass(src, srcpitch, dst, dstpitch, mfd->trow, fa->dst.w, fa->dst.h, mfd->filter_width);
  778.         else
  779.             box_do_vertical_pass(dst, dstpitch, src, srcpitch, mfd->trow, fa->dst.w, fa->dst.h, mfd->filter_width);
  780.     }
  781.  
  782.     if (i & 1)
  783.         box_do_vertical_unsharp_pass(src, srcpitch, dst, dstpitch, fa->src.data, fa->src.pitch, mfd->trow, fa->dst.w, fa->dst.h, mfd->filter_width);
  784.     else
  785.         box_do_vertical_unsharp_pass(dst, dstpitch, src, srcpitch, fa->src.data, fa->src.pitch, mfd->trow, fa->dst.w, fa->dst.h, mfd->filter_width);
  786. #endif
  787.  
  788.     if (MMX_enabled)
  789.         __asm emms
  790.  
  791.     return 0;
  792. }
  793.  
  794.  
  795. int boxEndProc(FilterActivation *fa, const FilterFunctions *ff) {
  796.     BoxFilterData *mfd = (BoxFilterData *)fa->filter_data;
  797.  
  798.     freemem(mfd->rows);    mfd->rows = NULL;
  799.     freemem(mfd->trow);    mfd->trow = NULL;
  800.  
  801.     return 0;
  802. }
  803.  
  804. long boxParamProc(FilterActivation *fa, const FilterFunctions *ff) {
  805. #ifndef DO_UNSHARP_FILTER
  806.     fa->dst.offset = fa->src.offset;
  807.     return 0;
  808. #else
  809.     return FILTERPARAM_SWAP_BUFFERS;
  810. #endif
  811. }
  812.  
  813.  
  814. BOOL CALLBACK boxConfigDlgProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam) {
  815.     BoxFilterData *mfd = (BoxFilterData *)GetWindowLong(hdlg, DWL_USER);
  816.     HWND hwndInit;
  817.     char buf[64];
  818.  
  819.     switch(msg) {
  820.         case WM_INITDIALOG:
  821.             SetWindowLong(hdlg, DWL_USER, lParam);
  822.             mfd = (BoxFilterData *)lParam;
  823.  
  824.             hwndInit = GetDlgItem(hdlg, IDC_SLIDER_WIDTH);
  825.             SendMessage(hwndInit, TBM_SETRANGE, TRUE, MAKELONG(1,48));
  826.             SendMessage(hwndInit, TBM_SETPOS, TRUE, mfd->filter_width);
  827.  
  828.             hwndInit = GetDlgItem(hdlg, IDC_SLIDER_POWER);
  829.             SendMessage(hwndInit, TBM_SETRANGE, TRUE, MAKELONG(1,3));
  830.             SendMessage(hwndInit, TBM_SETPOS, TRUE, mfd->filter_power);
  831.  
  832.             mfd->ifp->InitButton(GetDlgItem(hdlg, IDC_PREVIEW));
  833.  
  834.             // cheat to initialize the labels
  835.  
  836.             mfd->filter_width = -1;
  837.             mfd->filter_power = -1;
  838.  
  839.         case WM_HSCROLL:
  840.             {
  841.                 static const char *const szPowers[]={ "1 - box", "2 - quadratic", "3 - cubic" };
  842.                 int new_width, new_power;
  843.  
  844.                 new_width = SendDlgItemMessage(hdlg, IDC_SLIDER_WIDTH, TBM_GETPOS, 0, 0);
  845.                 new_power = SendDlgItemMessage(hdlg, IDC_SLIDER_POWER, TBM_GETPOS, 0, 0);
  846.  
  847.                 if (new_width != mfd->filter_width || new_power != mfd->filter_power) {
  848.                     mfd->filter_width = new_width;
  849.                     mfd->filter_power = new_power;
  850.  
  851.                     sprintf(buf, "radius %d", mfd->filter_width + mfd->filter_power - 1);
  852.                     SetDlgItemText(hdlg, IDC_STATIC_WIDTH, buf);
  853.  
  854.                     SetDlgItemText(hdlg, IDC_STATIC_POWER, szPowers[new_power-1]);
  855.  
  856.                     mfd->ifp->RedoFrame();
  857.                 }
  858.             }
  859.             return TRUE;
  860.  
  861.         case WM_COMMAND:
  862.             switch(LOWORD(wParam)) {
  863.             case IDOK:
  864.                 EndDialog(hdlg, 0);
  865.                 return TRUE;
  866.             case IDCANCEL:
  867.                 EndDialog(hdlg, 1);
  868.                 return TRUE;
  869.             case IDC_PREVIEW:
  870.                 mfd->ifp->Toggle(hdlg);
  871.                 return TRUE;
  872.             }
  873.             break;
  874.  
  875.     }
  876.  
  877.     return FALSE;
  878. }
  879.  
  880. int boxConfigProc(FilterActivation *fa, const FilterFunctions *ff, HWND hwnd) {
  881.     BoxFilterData *mfd = (BoxFilterData *)fa->filter_data;
  882.     BoxFilterData mfd_old;
  883.     int res;
  884.  
  885.     mfd_old = *mfd;
  886.     mfd->ifp = fa->ifp;
  887.  
  888.     res = DialogBoxParam(g_hInst,
  889.             MAKEINTRESOURCE(IDD_FILTER_BOX), hwnd,
  890.             boxConfigDlgProc, (LPARAM)mfd);
  891.  
  892.     if (res)
  893.         *mfd = mfd_old;
  894.  
  895.     return res;
  896. }
  897.  
  898. void boxStringProc(const FilterActivation *fa, const FilterFunctions *ff, char *str) {
  899.     BoxFilterData *mfd = (BoxFilterData *)fa->filter_data;
  900.  
  901.     wsprintf(str, " (radius %d, power %d)", mfd->filter_width+mfd->filter_power-1, mfd->filter_power);
  902. }
  903.  
  904. void boxScriptConfig(IScriptInterpreter *isi, void *lpVoid, CScriptValue *argv, int argc) {
  905.     FilterActivation *fa = (FilterActivation *)lpVoid;
  906.     BoxFilterData *mfd = (BoxFilterData *)fa->filter_data;
  907.  
  908.     mfd->filter_width    = argv[0].asInt();
  909.     mfd->filter_power    = argv[1].asInt();
  910. }
  911.  
  912. bool boxFssProc(FilterActivation *fa, const FilterFunctions *ff, char *buf, int buflen) {
  913.     BoxFilterData *mfd = (BoxFilterData *)fa->filter_data;
  914.  
  915.     _snprintf(buf, buflen, "Config(%d, %d)",
  916.         mfd->filter_width,
  917.         mfd->filter_power);
  918.  
  919.     return true;
  920. }
  921.  
  922.